<template>
    <div>
        <el-card style="margin: 0px 0px 20px; padding: 20px 0px;" shadow="always">
            <CategorySelect @getCategoryId="getCategoryId" :isShow="!isShowTable"></CategorySelect>
        </el-card>
        <el-card style="border: 1px solid #eee;" :shadow="isShowTable?'never':'always'">
            <div v-show="isShowTable">
                <!-- 添加属性按钮 -->
                <el-button type="primary" icon="el-icon-plus" :disabled="!category3Id"
                    style="margin-bottom: 20px; width: 120px;" @click="addAttrInfo">添加</el-button>
                <!-- 属性列表 -->
                <el-table :data="attrInfoList" stripe border empty-text="暂无数据" width="100%" max-height="960">
                    <el-table-column type="index" label="序号" width="120" align="center"></el-table-column>
                    <el-table-column prop="attrName" label="属性名称" width="400" align="left"></el-table-column>
                    <el-table-column prop="prop" label="属性值列表" width="width" align="left">
                        <template slot-scope="{row,$index}">
                            <el-tag style="margin-right:20px;" v-for="(item,index) in row.attrValueList" :key="item.id">
                                {{item.valueName}}
                            </el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column prop="prop" label="操作" width="260" align="center">
                        <template slot-scope="{row,$index}">
                            <el-button type="primary" icon="el-icon-" size="small" @click="editAttrInfo(row)">修改
                            </el-button>
                            <el-button type="danger" icon="el-icon-delete" size="small" @click="deleteAttrInfo(row)">删除
                            </el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
            <!-- 添加平台属性 -->
            <div v-show="!isShowTable">
                <el-form label-width="80px" :model="attrInfo">
                    <!-- 属性名输入框 -->
                    <el-form-item label="属性名" label-width="width">
                        <el-input style="width: 220px;" placeholder="请输入属性名" v-model="attrInfo.attrName"></el-input>
                    </el-form-item>
                    <!-- 添加属性值确认、取消按钮 -->
                    <el-button type="primary" icon="el-icon-plus" :disabled="!attrInfo.attrName" @click="addAttrValue"
                        style="margin-right: 20px; margin-bottom: 20px;">
                        添加属性值</el-button>
                    <!-- <el-button @click="isShowTable=true">取消</el-button> -->
                    <!-- 属性值列表 -->
                    <el-table :data="attrInfo.attrValueList" stripe border empty-text="暂无数据" width="100%">
                        <el-table-column type="index" label="序号" width="120" align="center"></el-table-column>

                        <el-table-column prop="valueName" label="属性名称" width="width" align="center">
                            <template slot-scope="{row,$index}">
                                <el-input placeholder="请输入属性值" v-model="row.valueName" size="small" v-show="row.isEdit"
                                    @blur="toLook(row)" @keyup.native.enter="toLook(row)" :ref="$index">
                                </el-input>
                                <span v-show="!row.isEdit" @click="toedit(row,$index)"
                                    style="display: block;">{{row.valueName}}</span>
                            </template>
                        </el-table-column>

                        <el-table-column prop="prop" label="操作" width="300" align="center">
                            <template slot-scope="{row,$index}">
                                <el-popconfirm :title='`确定删除${row.valueName}吗？`' @onConfirm="deleteAttrValue($index)">
                                    <el-button slot="reference" type="danger" icon="el-icon-delete" size="small">
                                        删除
                                    </el-button>
                                </el-popconfirm>
                            </template>
                        </el-table-column>

                    </el-table>
                    <!-- 确认、取消添加属性按钮 -->
                    <el-button type="primary" @click="saveAttrInfo" :disabled="attrInfo.attrValueList.length<1">保存
                    </el-button>
                    <el-button style="margin-left: 20px;margin-top: 20px;" @click="isShowTable=true">取消</el-button>
                </el-form>
            </div>
        </el-card>
    </div>
</template>
<script>
    import cloneDeep from 'lodash/cloneDeep'
    export default {
        name: "Attr",
        data() {
            return {
                category1Id: '', // 一级分类id
                category2Id: '', // 二级分类id
                category3Id: '', // 三级分类id
                attrInfoList: [], // 三级联动的数据
                isShowTable: true, // 是否展示平台属性列表
                attrInfo: { // 收集新增|修改平台属性
                    attrName: "", // 属性名
                    attrValueList: [], // 属性值列表
                    categoryId: 0, // 三级分类id
                    categoryLevel: 3, // 几级分类 | 服务器需要区分几级分类

                }
            }
        },
        methods: {
            // 通过自定义事件获取子组件的id
            getCategoryId({ categoryId, level }) {
                if (level == 1) { // 一级分类id
                    this.category1Id = categoryId
                    // 一级分类切换时清空二，三级分类id和三级联动的数据
                    this.category2Id = ''
                    this.category3Id = ''
                    this.attrInfoList = []
                } else if (level == 2) { // 二级分类id
                    this.category2Id = categoryId
                    // 二级分类切换时清空三级分类id和三级联动的数据
                    this.category3Id = ''
                    this.attrInfoList = []
                } else { // 三级分类
                    this.category3Id = categoryId
                    this.getAttrInfoList() // 发送请求获取三级联动的数据
                }
            },
            // 发送请求获取平台属性列表数据
            async getAttrInfoList() {
                const { category1Id, category2Id, category3Id } = this //解构出三级联动的三个id
                // 获取平台属性列表数据
                const result = await this.$api.attr.reqGetAttrInfoList(category1Id, category2Id, category3Id)
                if (result.code === 200) {
                    this.attrInfoList = result.data // 将平台属性列表数据保存在本地
                }
            },
            // 添加平台属性
            addAttrInfo() {
                this.isShowTable = false // 隐藏table
                // 清除上次编辑的数据,并收集三级分类的id
                this.attrInfo = { // 收集新增|修改平台属性
                    attrName: "", // 属性名
                    attrValueList: [], // 属性值列表
                    categoryId: this.category3Id, // 三级分类id
                    categoryLevel: 3, // 几级分类 | 服务器需要区分几级分类
                }

            },
            // 修改平台属性
            editAttrInfo(row) {
                this.isShowTable = false //隐藏table
                // 将平台属性展示出来 
                // 修改数据时不可以直接赋值数据，此处需要进行深拷贝
                // 如果对象结构不复杂可通过 {...object}来进行浅拷贝
                this.attrInfo = cloneDeep(row)

                // 给每个数据添加 isEdit 标记是否可编辑
                this.attrInfo.attrValueList.forEach(item => {
                    // 遍历响应式数据 并给每个对象上添加一条数据，vue检测不到该数据，该数据不是响应式，视图无法跟着改变。
                    // item.isEdit = false // 该写法无法实现响应式

                    // 通过 $set 方法可将新增的数据改为响应式
                    // 写法：this.$set("被添加数据的对象","变量名","变量值")
                    this.$set(item, 'isEdit', false) // 可实现响应式
                });
            },
            // 添加属性值
            addAttrValue() {
                // 对响应式数据的push新的数据，vue会检测到新增的数据并将其变成响应式数据
                this.attrInfo.attrValueList.push({
                    isEdit: true,
                    attrId: this.attrInfo.id ? this.attrInfo.id : undefined, // 属性id | 修改属性需将服务器传过来的id带上，添加属性需将其设为undefined
                    valueName: "" // 属性值
                })
                this.$nextTick(() => {
                    // 新增属性值时聚焦input
                    // 新增的属性值永远是数组中的最后一位，所以对应的ref就是 数组长度 - 1
                    this.$refs[this.attrInfo.attrValueList.length - 1].focus()
                })
            },
            // 切换属性值为查看模式
            toLook(row) {
                // 判断输入的值是否符合要求
                if (row.valueName.trim() == '') { // 当输入的值是空格时
                    this.$message({
                        message: '请输入正确格式的属性值',
                        type: 'warning'
                    });
                    return; // 直接返回不再执行函数，方便用户再次输入
                }
                let isRepeat = this.attrInfo.attrValueList.some(item => { //item为数组中的每个元素
                    if (row !== item) { // 此处的row为数组中的最后一项 需要用row和除row之外的每一项做比较
                        return row.valueName == item.valueName // 当最新输入的valueName和之前的valueName有重复时，返回true
                    }
                })
                if (isRepeat) { // 当输入重复时
                    this.$message({
                        message: '不能输入重复的属性名，请重新输入',
                        type: 'warning'
                    });
                    return; // 直接返回不再执行函数，方便用户再次输入
                }
                row.isEdit = false // 修改为查看状态
            },
            // 切换属性值为编辑模式
            toedit(row, index) {
                row.isEdit = true //修改input为编辑状态

                // 点击span切换为input时，页面会重新渲染一次，此时直接获取input获取不到
                // 通过 $nextTick(()=>{}) 回调会等页面渲染完毕后在执行回调里的代码
                this.$nextTick(() => {
                    // 通过为每个input添加的ref，来获取到该节点，在通过focus方法实现聚焦（element自带的方法）
                    this.$refs[index].focus()
                })
            },
            // 删除属性值
            deleteAttrValue(index) {
                // 删除当前点击的属性值
                // splice 删除数组中的元素 改变原数组
                this.attrInfo.attrValueList.splice(index, 1) // 从 index 位置起删除 1 位
            },
            // 添加属性/保存属性 发送请求并携带相关参数
            async saveAttrInfo() {
                // 整理参数
                // 1、属性值不能为空，过滤掉属性值为空的元素
                // 2、给服务器携带的参数中不需要含有 isEdit 属性
                this.attrInfo.attrValueList = this.attrInfo.attrValueList.filter(item => {
                    if (item.valueName !== '') { // 过滤掉属性值为空的元素
                        delete item.isEdit // 删除isEdit属性
                        return true;
                    }
                })
                try {
                    // 发送请求
                    await this.$api.attr.reqAddOrUpdataAttr(this.attrInfo)
                    // 弹框提示保存成功
                    this.$message({
                        message: '保存成功!',
                        type: 'success'
                    })
                    this.getAttrInfoList() // 重新获取属性列表数据
                    this.isShowTable = true // 退出添加平台是属性
                } catch (error) {
                    // 弹框提示保存失败
                    this.$message({
                        message: '保存失败!',
                        type: 'error'
                    })
                }
            },
            // 删除平台属性
            async deleteAttrInfo(row) {
                this.$confirm(`您确定要删除${row.attrName}吗？`, '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(async () => { // 点击确认按钮
                    // 业务逻辑 | 删除并再次获取平台属性列表
                    const result = await this.$api.attr.reqDeleteAttr(row.id)
                    if (result.code === 200) { // 请求成功
                        this.getAttrInfoList() // 重新获取平台属性列表数据
                        this.$message({ //删除完成重新获取平台属性列表数据后弹框显示
                            type: 'success',
                            message: '删除成功!',
                            center: true
                        });
                    }
                }).catch((error) => {
                    if (error === 'cancel') { // 点击取消按钮
                        this.$message({
                            type: 'info',
                            message: '已取消删除',
                            center: true
                        });
                    }
                });
            },


        },
    }
</script>
<style>

</style>